package com.derbysoft.ota.application.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.application.translator.CodeTables;
import com.derbysoft.ota.application.translator.rs.ErrorsTranslator;
import com.derbysoft.ota.application.translator.rs.WarningsTranslator;
import com.derbysoft.ota.application.util.Beans;
import com.derbysoft.ota.application.util.PayloadStdAttributes;
import com.derbysoft.ota.infrastructure.context.RoutingContext;
import com.derbysoft.ota.infrastructure.context.RoutingContextHolder;
import com.derbysoft.ota.interfaces.protocol._2009a.POSType;
import com.derbysoft.ota.interfaces.protocol._2009a.SuccessType;
import com.derbysoft.ota.interfaces.protocol._2009a.UniqueIDType;
import com.derbysoft.remote.dswitch.core.DestinationDTO;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.core.RequestHeader;
import com.derbysoft.remote.dswitch.generic.dto.UniqueIDDTO;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebService;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebServiceFactory;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.googlecode.functionalcollections.FunctionalIterables;

public abstract class AbstractService {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	protected DSwitch4HotelBuyerWebServiceFactory dswitch4HotelBuyerWebServiceFactory;
	protected Translator<POSType, RequestHeader> requestHeaderTranslator;
	protected ErrorsTranslator errorsTranslator = new ErrorsTranslator();
	protected WarningsTranslator warningsTranslator = new WarningsTranslator();

	public AbstractService(
		DSwitch4HotelBuyerWebServiceFactory dswitch4HotelBuyerWebServiceFactory,
		Translator<POSType, RequestHeader> requestHeaderTranslator) {
		
		this.dswitch4HotelBuyerWebServiceFactory = dswitch4HotelBuyerWebServiceFactory;
		this.requestHeaderTranslator = requestHeaderTranslator;
	}

	protected RequestHeader requestHeader(POSType posType) {
	    return requestHeader(posType, Lists.<UniqueIDType>newArrayList(), false);
	}	
	
	protected RequestHeader requestHeader(POSType pos, Iterable<? extends UniqueIDType> uniqueIds, boolean destinationRequired) {
		RequestHeader requestHeader = requestHeaderTranslator.translate(pos);
		
		UniqueIDType wholesaler = FunctionalIterables.make(uniqueIds).detect(new Predicate<UniqueIDType>() {
			public boolean apply(UniqueIDType input) {
				return CodeTables.UIT_WHOLESALER.equals(input.getType());
			}
		});
		
		if (destinationRequired && wholesaler == null) {
			throw new IllegalStateException("Please provide us the UniqueIDType of 'Wholesaler'(CodeTable -> UIT -> 7) so that we can decide which wholsaler you selected.");
		} 
		
		String destination = null;
		if (wholesaler != null) {
			DestinationDTO singleDestination = new DestinationDTO();
			destination = wholesaler.getID();
			singleDestination.setUniqueID(
				new UniqueIDDTO(
					destination, 
					com.derbysoft.remote.dswitch.generic.constants.UniqueIDType.HOTEL
				)
			);
			requestHeader.setDestinations(Lists.newArrayList(singleDestination));			
		}
		
		RoutingContextHolder.set(RoutingContext.of(requestHeader.getSource().getUniqueID().getId(), destination));
		return requestHeader;
	}

	protected DSwitch4HotelBuyerWebService dswitch() {
	    return dswitch4HotelBuyerWebServiceFactory.getDSwitch4HotelBuyerWebService();
	}
    
    /**
     * Handle generic response returned by dswitch.
     * @param switchRS response returned by dswitch.
     * @param otaRQ ota request object.
     * @param otaRS ota response object.
     * @return <code>true</code> if got an error, <code>false</code> on the other hand.
     */
	protected boolean handleResponseHeaders(GenericRS<?> switchRS, Object otaRQ, Object otaRS) {
		PayloadStdAttributes.copy(otaRQ, otaRS);
		if (switchRS.hasErrors()) {
			logger.error("Got an error from dswitch : " + switchRS.getErrors());
			Beans.setProperty(otaRS, "errors", errorsTranslator.translate(switchRS.getErrors()));
			return true;
		} else {
			if (switchRS.getWarnings() != null) {
				Beans.setProperty(otaRS, "warnings", warningsTranslator.translate(switchRS.getWarnings()));
			}
			Beans.setProperty(otaRS, "success", new SuccessType());
		}
		return false;
	}
	
}
